#ifndef __APP_LOG_H__
#define __APP_LOG_H__

#ifdef CONFIG_LOG_OUTPUT

//#define CONFIG_APP_LOG_SHOW_TAGS //show tag default

/* Log tag name */
#ifdef CONFIG_APP_LOG_SHOW_TAGS
#define APP_LOG_TAG_ERR         "[ERR]"
#define APP_LOG_TAG_WRN         "[WRN]"
#define APP_LOG_TAG_INF         "[INF]"
#define APP_LOG_TAG_DBG         "[DBG]"
#define APP_LOG_TAG_VBS         "[VBS]"
#else
#define APP_LOG_TAG_ERR         ""
#define APP_LOG_TAG_WRN         ""
#define APP_LOG_TAG_INF         ""
#define APP_LOG_TAG_DBG         ""
#define APP_LOG_TAG_VBS         ""
#endif /* CONFIG_APP_LOG_SHOW_TAGS */

/* Log domain name */
#ifndef APP_LOG_DOMAIN
#define APP_LOG_DOMAIN          "general"
#endif

/* Log level value */
#define APP_LOG_LEVEL_OFF       0
#define APP_LOG_LEVEL_ERROR     1
#define APP_LOG_LEVEL_WARNING   2
#define APP_LOG_LEVEL_INFO      3
#define APP_LOG_LEVEL_DEBUG     4
#define APP_LOG_LEVEL_VERBOSE   5

/* Log level */
#ifndef APP_LOG_LEVEL
#define APP_LOG_LEVEL           APP_LOG_LEVEL_INFO //default log level
#endif

#if APP_LOG_LEVEL >= APP_LOG_LEVEL_ERROR
#define LOG_ERR(format, ...)                    do{printf("%s[%s] ", APP_LOG_TAG_ERR, APP_LOG_DOMAIN); printf(format,  ## __VA_ARGS__); printf("\n");}while(0)
#define LOG_ERR_ARRAY(array, len)               do{int __i; for(__i=0;__i<(len);++__i)printf("%02X ",((uint8_t *)(array))[__i]);}while(0)
#define LOG_ERR_ARRAY_EX(note, array, len)      do{printf("%s[%s] %s: ", APP_LOG_TAG_ERR, APP_LOG_DOMAIN, note); LOG_ERR_ARRAY(array, len); printf("[%d bytes]\n", len);}while(0)
#define LOG_ERR_FUNC()                          do{LOG_ERR("%s @ %d %s", __FUNCTION__, __LINE__, __FILE__);}while(0)
#define LOG_ERR_NULL()                          do{printf("\n");}while(0)
#else
#define LOG_ERR(format, ...)
#define LOG_ERR_ARRAY(array, len)
#define LOG_ERR_ARRAY_EX(note, array, len)
#define LOG_ERR_FUNC()
#define LOG_ERR_NULL()
#endif /* APP_LOG_LEVEL >= APP_LOG_LEVEL_ERROR */

#if APP_LOG_LEVEL >= APP_LOG_LEVEL_WARNING
#define LOG_WRN(format, ...)                    do{printf("%s[%s] ", APP_LOG_TAG_WRN, APP_LOG_DOMAIN); printf(format,  ## __VA_ARGS__); printf("\n");}while(0)
#define LOG_WRN_ARRAY(array, len)               do{int __i; for(__i=0;__i<(len);++__i)printf("%02X ",((uint8_t *)(array))[__i]);}while(0)
#define LOG_WRN_ARRAY_EX(note, array, len)      do{printf("%s[%s] %s: ", APP_LOG_TAG_WRN, APP_LOG_DOMAIN, note); LOG_WRN_ARRAY(array, len); printf("[%d bytes]\n", len);}while(0)
#define LOG_WRN_FUNC()                          do{LOG_WRN("%s @ %d %s", __FUNCTION__, __LINE__, __FILE__);}while(0)
#define LOG_WRN_NULL()                          do{printf("\n");}while(0)
#else
#define LOG_WRN(format, ...)
#define LOG_WRN_ARRAY(array, len)
#define LOG_WRN_ARRAY_EX(note, array, len)
#define LOG_WRN_FUNC()
#define LOG_WRN_NULL()
#endif /* APP_LOG_LEVEL >= APP_LOG_LEVEL_WARNING */

#if APP_LOG_LEVEL >= APP_LOG_LEVEL_INFO
#define LOG_INF(format, ...)                    do{printf("%s[%s] ", APP_LOG_TAG_INF, APP_LOG_DOMAIN); printf(format,  ## __VA_ARGS__); printf("\n");}while(0)
#define LOG_INF_ARRAY(array, len)               do{int __i; for(__i=0;__i<(len);++__i)printf("%02X ",((uint8_t *)(array))[__i]);}while(0)
#define LOG_INF_ARRAY_EX(note, array, len)      do{printf("%s[%s] %s: ", APP_LOG_TAG_INF, APP_LOG_DOMAIN, note); LOG_INF_ARRAY(array, len); printf("[%d bytes]\n", len);}while(0)
#define LOG_INF_FUNC()                          do{LOG_INF("%s @ %d %s", __FUNCTION__, __LINE__, __FILE__);}while(0)
#define LOG_INF_NULL()                          do{printf("\n");}while(0)
#else
#define LOG_INF(format, ...)
#define LOG_INF_ARRAY(array, len)
#define LOG_INF_ARRAY_EX(note, array, len)
#define LOG_INF_FUNC()
#define LOG_INF_NULL()
#endif /* APP_LOG_LEVEL >= APP_LOG_LEVEL_INFO */

#if 1 //APP_LOG_LEVEL >= APP_LOG_LEVEL_DEBUG
#define LOG_DBG(format, ...)                    do{printf("%s[%s] ", APP_LOG_TAG_DBG, APP_LOG_DOMAIN); printf(format,  ## __VA_ARGS__); printf("\n");}while(0)
#define LOG_DBG_ARRAY(array, len)               do{int __i; for(__i=0;__i<(len);++__i)printf("%02X ",((uint8_t *)(array))[__i]);}while(0)
#define LOG_DBG_ARRAY_EX(note, array, len)      do{printf("%s[%s] %s: ", APP_LOG_TAG_DBG, APP_LOG_DOMAIN, note); LOG_DBG_ARRAY(array, len); printf("[%d bytes]\n", len);}while(0)
#define LOG_DBG_FUNC()                          do{LOG_DBG("%s @ %d %s", __FUNCTION__, __LINE__, __FILE__);}while(0)
#define LOG_DBG_NULL()                          do{printf("\n");}while(0)
#else
#define LOG_DBG(format, ...)
#define LOG_DBG_ARRAY(array, len)
#define LOG_DBG_ARRAY_EX(note, array, len)
#define LOG_DBG_FUNC()
#define LOG_DBG_NULL()
#endif /* APP_LOG_LEVEL >= APP_LOG_LEVEL_DEBUG */

#if APP_LOG_LEVEL >= APP_LOG_LEVEL_VERBOSE
#define LOG_VBS(format, ...)                    do{printf("%s[%s] ", APP_LOG_TAG_DBG, APP_LOG_DOMAIN); printf(format,  ## __VA_ARGS__); printf("\n");}while(0)
#define LOG_VBS_ARRAY(array, len)               do{int __i; for(__i=0;__i<(len);++__i)printf("%02X ",((uint8_t *)(array))[__i]);}while(0)
#define LOG_VBS_ARRAY_EX(note, array, len)      do{printf("%s[%s] %s: ", APP_LOG_TAG_DBG, APP_LOG_DOMAIN, note); LOG_DBG_ARRAY(array, len); printf("[%d bytes]\n", len);}while(0)
#define LOG_VBS_FUNC()                          do{LOG_VBS("%s @ %d %s", __FUNCTION__, __LINE__, __FILE__);}while(0)
#define LOG_VBS_NULL()                          do{printf("\n");}while(0)
#else
#define LOG_VBS(format, ...)
#define LOG_VBS_ARRAY(array, len)
#define LOG_VBS_ARRAY_EX(note, array, len)
#define LOG_VBS_FUNC()
#define LOG_VBS_NULL()
#endif /* APP_LOG_LEVEL >= APP_LOG_LEVEL_VERBOSE */

#else

#define LOG_ERR(format, ...)
#define LOG_ERR_ARRAY(array, len)
#define LOG_ERR_ARRAY_EX(note, array, len)
#define LOG_ERR_FUNC()
#define LOG_ERR_NULL()

#define LOG_WRN(format, ...)
#define LOG_WRN_ARRAY(array, len)
#define LOG_WRN_ARRAY_EX(note, array, len)
#define LOG_WRN_FUNC()
#define LOG_WRN_NULL()

#define LOG_INF(format, ...)
#define LOG_INF_ARRAY(array, len)
#define LOG_INF_ARRAY_EX(note, array, len)
#define LOG_INF_FUNC()
#define LOG_INF_NULL()

#define LOG_DBG(format, ...)
#define LOG_DBG_ARRAY(array, len)
#define LOG_DBG_ARRAY_EX(note, array, len)
#define LOG_DBG_FUNC()
#define LOG_DBG_NULL()

#define LOG_VBS(format, ...)
#define LOG_VBS_ARRAY(array, len)
#define LOG_VBS_ARRAY_EX(note, array, len)
#define LOG_VBS_FUNC()
#define LOG_VBS_NULL()

#endif /* CONFIG_LOG_OUTPUT */

#endif
